//=========================================================================
// Copyright (C) 2024 The C++ Component Model(COMO) Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=========================================================================

#ifndef __MATHUTILS_H__
#define __MATHUTILS_H__

#ifdef __cplusplus
extern "C"
{
#endif

#include "int64.h"

typedef enum tagDataState {
    DATA_NULL = 0,
    DATA_READY
} DataState;

/**
 * 真假值通过具有足够码距的编码来表示：
 *    HEX: 55AA == BIN: 0101010110101010
 *    HEX: AA55 == BIN: 1010101001010101
 */
typedef enum tagVOTING_RESULT {
    VOTING_NULL  = 0,
    VOTING_PASS  = 0x55AAu,
    VOTING_FAIL  = 0xAA55u
} VOTING_RESULT;

#ifdef __DONNOT_SUPPORT_VOTING_BIGDATA
#define MAX_VOTING_DATA_SIZE    8       // 最大表决数据，只保留占位的数据
#else
#define MAX_VOTING_DATA_SIZE    32000   // 最大表决数据尺寸
#endif

typedef struct tagBigVotingData {
#if defined(BIG_VOTING_DATA_HEAD_SIZE) && (BIG_VOTING_DATA_HEAD_SIZE > 0)
    unsigned char head[BIG_VOTING_DATA_HEAD_SIZE];
#endif
    unsigned char bytes[MAX_VOTING_DATA_SIZE];
} BigVotingData;

int FindMode(Int64 *arr, int size, int atleast, DataState *dataState);
int MajorityElement(Int64 *nums, int numsSize, int atleast, DataState *dataState);
int memcmp_arithmetic(const void* s1, const void* s2, size_t n);

int BigDataVoter(BigVotingData *arr, size_t arrSize, size_t dataSize,
                                     DataState *dataState, int atleastClients,
                                     VOTING_RESULT *votingResult);

uint64_t distance_mod(uint64_t prev, uint64_t curr, uint64_t N);
bool is_next_range(uint64_t prev, uint64_t curr,
                              uint64_t N, uint64_t step_min, uint64_t step_max);
uint64_t counter_next(uint64_t current, uint64_t N, uint64_t step);

#ifdef __cplusplus
}
#endif

#endif // __MATHUTILS_H__
